<template>
  <div class="app-container">
    <el-card>
      <div>
        <el-button size="small" type="primary" @click="handleClick('add')"
          >新增</el-button
        >
      </div>
      <div class="have-pagination-container">
        <el-table v-loading="loading.list" :data="list" border>
          <el-table-column label="ID" prop="id" width="100"></el-table-column>
          <el-table-column label="角色名称" prop="name"></el-table-column>
          <el-table-column label="角色code" prop="code"></el-table-column>
          <el-table-column
            label="角色描述"
            prop="description"
          ></el-table-column>
          <el-table-column label="创建时间" prop="createDate"></el-table-column>
          <el-table-column label="是否启用" align="center" width="100">
            <template slot-scope="scope">
              <el-switch
                v-model="scope.row.isOpen"
                @change="onSwitchChange($event, scope.row)"
              ></el-switch>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button
                type="text"
                size="small"
                @click="handleClick('authSet', scope.row)"
                >权限配置</el-button
              >
              <el-button
                type="text"
                size="small"
                @click="handleClick('update', scope.row)"
                >修改</el-button
              >
              <el-button
                type="text"
                size="small"
                @click="handleClick('remove', scope.row)"
                >删除</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div class="pagination-box">
        <el-pagination small
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="pageNo"
          :page-sizes="pageSizeOpts"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="totalCount"
        >
        </el-pagination>
      </div>
    </el-card>

    <el-dialog
      :close-on-click-modal="false"
      :title="handleType == 'add' ? '新增' : '修改'"
      :visible.sync="updateDialog"
      width="30%"
    >
      <el-form
        ref="updateForm"
        :model="updateForm"
        :rules="updateFormRule"
        label-width="80px"
      >
        <el-form-item label="角色名称" prop="name">
          <el-input
            v-model="updateForm.name"
            class="el-input__small"
          ></el-input>
        </el-form-item>
        <el-form-item label="角色code" prop="code">
          <el-input
            v-model="updateForm.code"
            class="el-input__small"
          ></el-input>
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input type="textarea" v-model="updateForm.description"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="updateDialog = false">取 消</el-button>
        <el-button type="primary" @click="handleSure">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 权限配置 -->
    <el-dialog
      :close-on-click-modal="false"
      :title="`权限配置(${tmpRow.name})`"
      :visible.sync="authDialog"
      width="90%"
    >
      <el-table
        v-loading="loading.menuTree"
        ref="multiTable"
        :data="menuTree"
        style="width: 100%; margin-bottom: 20px"
        row-key="id"
        border
        default-expand-all
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      >
        <el-table-column type="index" width="55">
          <template slot="header" slot-scope="scope">
            <el-checkbox
              v-model="checkAll"
              :indeterminate="isIndeterminate"
              @change="onCheckedChange($event, 'all')"
            ></el-checkbox>
          </template>
          <template slot-scope="scope">
            <el-checkbox
              v-model="scope.row.checked"
              @change="onCheckedChange($event, 'single', scope.row)"
            ></el-checkbox>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="名称" width="180"></el-table-column>
        <el-table-column align="center" label="类型" width="100">
          <template slot-scope="scope">
            <el-tag v-if="scope.row.type == 1">目录</el-tag>
            <el-tag v-if="scope.row.type == 2" type="success">菜单</el-tag>
            <el-tag v-if="scope.row.type == 3" type="warning">按钮</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="CODE" prop="code"> </el-table-column>
        <el-table-column label="URL" prop="url"> </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="authDialog = false">取 消</el-button>
        <el-button type="primary" @click="setRoleMenu">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { requiredFormValidate } from "@/utils/validate.js";
import {
  setRoleMenu,
  selectMenuTreeByRoleId,
  sysrole_add,
  sysrole_delete,
  sysrole_update,
  sysrole_list,
} from "@/api/platformSys";

const getDefaultForm = () => ({
  name: null,
  code: null,
  description: null,
});

export default {
  data() {
    return {
      tmpRow: {},
      checkAll: false,
      isIndeterminate: false,
      handleType: "",
      list: [],
      menuTree: [],
      menuTreeDeep: 0,
      checkedCount: 0,
      loading: {
        list: true,
        menuTree: true,
      },
      updateForm: getDefaultForm(),
      updateFormRule: {
        name: [{ validator: requiredFormValidate, trigger: "blur" }],
        code: [{ validator: requiredFormValidate, trigger: "blur" }],
        description: [{ validator: requiredFormValidate, trigger: "blur" }],
      },
      pageNo: 1,
      pageSize: 20,
      totalCount: 0,
      pageSizeOpts: [20, 50, 100, 300, 500],
      updateDialog: false,
      authDialog: false,
    };
  },
  created() {
    this.getData();
  },
  methods: {
    getMenuTree(id, callback = () => {}) {
      this.loading.menuTree = true;
      selectMenuTreeByRoleId({
        id,
      }).then(({ result = {} }) => {
        this.menuTree = result.treeList;
        this.menuTreeDeep = result.treeSize;
        this.checkedCount = result.checkedSize;
        this.loading.menuTree = false;
        callback();
      });
    },
    getData() {
      this.loading.list = true;
      sysrole_list(
        {
          pageNo: this.pageNo,
          pageSize: this.pageSize
        }
      ).then((res) => {
        this.list = res.result.data.map((d) => {
          d.isOpen = d.isOpen == 1;
          return d;
        });
        this.totalCount = res.result.totalCount;
        this.loading.list = false;
      });
    },
    handleClick(type, row) {
      switch (type) {
        case "add":
        case "update":
          this.handleType = type;
          this.updateDialog = true;
          this.updateForm =
            type == "add"
              ? getDefaultForm()
              : Object.assign({}, row, {
                  isOpen: row.isOpen ? 1 : 0,
                });
          this.$nextTick(() => {
            this.$refs.updateForm.clearValidate();
          });
          break;
        case "authSet":
          this.authDialog = true;
          this.tmpRow = row;
          this.getMenuTree(row.id, this.dealCheckAll);
          break;
        case "remove":
          this.$confirm("此操作将永久删除该角色, 是否继续?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          }).then(() => {
            sysrole_delete({
              id: row.id,
            }).then((res) => {
              this.$message.success(res.msg || "操作成功");
              this.getData();
            });
          });
          break;
        default:
          return;
      }
    },
    handleSure() {
      let fn;
      this.$refs.updateForm.validate((valid) => {
        if (valid) {
          switch (this.handleType) {
            case "add":
              fn = sysrole_add;
              break;
            case "update":
              fn = sysrole_update;
              break;
            default:
              return;
          }
          fn(this.updateForm).then((res) => {
            this.updateDialog = false;
            this.$message.success(res.msg || "操作成功");
            this.getData();
          });
        } else {
          return false;
        }
      });
    },
    handleSizeChange(val) {
      this.pageSize = val;
      this.getData();
    },
    handleCurrentChange(val) {
      this.pageNo = val;
      this.getData();
    },
    onSwitchChange(flag, row) {
      row.isOpen = !flag;
      this.$confirm(`是否要${flag ? "启用" : "关闭"}该角色？`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        let data = Object.assign({}, row, {
          isOpen: flag ? 1 : 0,
        });
        sysrole_update(data).then((res) => {
          row.isOpen = flag;
          this.$message.success(res.msg || "操作成功");
        });
      });
    },

    // table-改造

    toggleChecked(ary, flag) {
      return ary.map((item) => {
        return {
          ...item,
          checked: flag,
          children: this.toggleChecked(item.children || [], flag),
        };
      });
    },
    toggleChecked2(ary, flag) {
      ary.forEach((item) => {
        item.checked = flag;
        if (Array.isArray(item.children) && item.children.length > 0) {
          this.toggleChecked2(item.children, flag);
        }
      });
    },
    getCheckedCount(ary, sum = 0, ids = []) {
      let childrenSum;
      ary.forEach((item) => {
        if (item.checked) {
          sum++;
          ids.push(item.id);
        }
        if (Array.isArray(item.children) && item.children.length > 0) {
          childrenSum = this.getCheckedCount(item.children, 0, ids);
          sum += childrenSum;
        }
      });
      return sum;
    },
    onCheckedChange(flag, type, row) {
      switch (type) {
        case "all":
          this.menuTree = this.toggleChecked(this.menuTree, flag);
          this.isIndeterminate = false;
          break;
        case "single":
          this.toggleChecked2([row], flag);
          this.menuTree = JSON.parse(JSON.stringify(this.menuTree));
          this.dealCheckAll();
          break;
        default:
          return;
      }
    },
    dealCheckAll(initVal = null) {
      let checkedCount;
      if (initVal != null) {
        checkedCount = initVal;
      } else {
        checkedCount = this.getCheckedCount(this.menuTree); // 勾选个数等于列表总数，isIndeterminate为false
      }
      this.checkAll = checkedCount == this.menuTreeDeep;
      this.isIndeterminate =
        checkedCount > 0 && checkedCount < this.menuTreeDeep;
    },
    setRoleMenu() {
      const { id } = this.tmpRow;
      const sysMenuIdList = [];
      this.getCheckedCount(this.menuTree, 0, sysMenuIdList);
      setRoleMenu({
        id,
        sysMenuIdList,
      }).then((res) => {
        this.$message.success(res.msg || "操作成功");
        this.authDialog = false;
      });
    },
  },
};
</script>
